﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace GT.UI.WinForms
{
    public partial class ProgressDialog
    {
        public event EventHandler Completed;
        public bool AllowDrag { get; set; }
        public bool OpenModal { get; set; }
        public Form HostForm { get; private set; }
        private ProgressBar Progress;
        private Label Status;

        private SubclassedWindow _subclassedWnd;

        public ProgressDialog()
        {
            AllowDrag = true;
            HostForm = CreateForm();
            _subclassedWnd = new SubclassedWindow();
            _subclassedWnd.WindowProc += new SubclassedWindow.WindowProcHandler(WndProc);
            _subclassedWnd.AssignHandle(HostForm.Handle);
            HostForm.FormClosing += (src, ev) =>
                {
                    if (ev.CloseReason == CloseReason.UserClosing)
                        ev.Cancel = true;
                };
        }

        private Form CreateForm()
        {
            Form f = new Form();
            f.FormBorderStyle = FormBorderStyle.Fixed3D;
            f.ShowIcon = false;
            f.ShowInTaskbar = false;
            f.MaximizeBox = false;
            f.MinimizeBox = false;
            f.StartPosition = FormStartPosition.CenterScreen;

            var layout = new TableLayoutPanel();
            layout.ColumnCount = 1;
            layout.RowCount = 2;
            layout.RowStyles.Add(new RowStyle(SizeType.Percent, 50f));
            layout.RowStyles.Add(new RowStyle(SizeType.Percent, 50f));
            layout.Dock = DockStyle.Fill;

            Status = new Label();
            Status.AutoSize = false;
            Status.TextAlign = ContentAlignment.MiddleCenter;
            Status.Dock = DockStyle.Fill;
            layout.Controls.Add(Status, 0, 0);

            Progress = new ProgressBar();
            Progress.Width = (int)(layout.Width * 0.75);
            Progress.Anchor = AnchorStyles.Left | AnchorStyles.Right;
            Progress.Style = ProgressBarStyle.Continuous;
            layout.Controls.Add(Progress, 0, 1);

            f.Width = 400;
            f.Height = 200;

            f.Controls.Add(layout);
            return f;
        }

        public string Title
        {
            get { return HostForm.Text; }
            set { HostForm.Text = value; }
        }

        public string Text
        {
            get
            {
                return Status.Text;
            }
            set
            {
                Status.Text = value;
            }
        }

        public ProgressBarStyle Style
        {
            get { return Progress.Style; }
            set { Progress.Style = value; }
        }

        public int Value
        {
            get { return Progress.Value; }
            set
            {
                Progress.Value = value;
                if (Progress.Value >= MaxValue)
                {
                    Completed.Raise(this);
                }
            }
        }

        public int MinValue
        {
            get { return Progress.Minimum; }
            set { Progress.Minimum = value; }
        }

        public int MaxValue
        {
            get { return Progress.Maximum; }
            set { Progress.Maximum = value; }
        }

        public ProgressDialog Open()
        {
            if (OpenModal)
                HostForm.ShowDialog();
            else
                HostForm.Show();
            return this;
        }

        public int SetValue(int value = 0)
        {
            Progress.Value = value;
            return Progress.Value;
        }

        public int SetValue(int completed = 0, int total = 100)
        {
            if (MinValue != 0) MinValue = 0;
            if (MaxValue != 100) MaxValue = 100;
            Progress.Value = (int)Math.Round((double)(completed * 100) / total, 0);
            return Progress.Value;
        }

        private void WndProc(ref Message message, ref bool handled) 
        { 
            const int WM_SYSCOMMAND = 0x0112; 
            const int SC_MOVE = 0xF010; 
 
            switch (message.Msg) 
            { 
                case WM_SYSCOMMAND: 
                   int command = message.WParam.ToInt32() & 0xfff0;
                   if (command == SC_MOVE && !AllowDrag)
                   {
                       handled = true;
                       return;
                   }
                   break; 
            } 
        }

        public static implicit operator Form(ProgressDialog dlg)
        {
            return dlg.HostForm;
        }

        public void Close()
        {
            HostForm.Hide();
        }
    }
}
